package com.ckw.common.netty;


import com.ckw.common.websocket.RequestUriUtils;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * WebSocket连接数据接受处理类
 */
@Slf4j
@ChannelHandler.Sharable
@Component
public class NioWebSocketHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    @Autowired
    private NioWebSocketChannelPool webSocketChannelPool;
    @Autowired
    private WebSocketProperties webSocketProperties;
    public final static boolean CTX = true;
    public static ConcurrentMap<String, ChannelHandlerContext> userWebSocketId = new ConcurrentHashMap<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.debug("客户端连接：{}", ctx.channel().id());
        webSocketChannelPool.addChannel(ctx.channel());
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.debug("客户端断开连接：{}", ctx.channel().id());
        webSocketChannelPool.removeChannel(ctx.channel());
        super.channelInactive(ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.channel().flush();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
        // 根据请求数据类型进行分发处理

        if (frame instanceof PingWebSocketFrame) {
            pingWebSocketFrameHandler(ctx, (PingWebSocketFrame) frame);
        } else if (frame instanceof TextWebSocketFrame) {
            textWebSocketFrameHandler(ctx, "","","");
        } else if (frame instanceof CloseWebSocketFrame) {
            closeWebSocketFrameHandler(ctx, (CloseWebSocketFrame) frame);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("客户端请求数据类型：{}", msg.getClass());
        if (msg instanceof FullHttpRequest) {
            fullHttpRequestHandler(ctx, (FullHttpRequest) msg);
        }
        super.channelRead(ctx, msg);
    }

    /**
     * 处理连接请求，客户端WebSocket发送握手包时会执行这一次请求
     * @param ctx
     * @param request
     */
    private void fullHttpRequestHandler(ChannelHandlerContext ctx, FullHttpRequest request) {
        String uri = request.uri();
        log.info("WebSocket连接URI: {}", uri); // 添加调试日志
        Map<String, String> params = RequestUriUtils.getParams(uri);
        log.info("解析参数: {}", params); // 打印参数
        // 1. 校验路径
        if (!webSocketProperties.getPath().equals(RequestUriUtils.getBasePath(uri))) {
            ctx.close();
            return;
        }

        // 2. 注册用户连接（确保id非空）
        String userId = params.get("id");
        if (userId != null && !userId.isEmpty()) {
            userWebSocketId.put(userId, ctx);
            log.info("注册WebSocket连接: userId={}, channelId={}", userId, ctx.channel().id());
            request.setUri(webSocketProperties.getPath()); // 重置URI
        } else {
            log.error("无效的用户ID: {}", uri);
            ctx.close();
        }
    }

    /**
     * 客户端发送断开请求处理
     * @param ctx
     * @param frame
     */
    private void closeWebSocketFrameHandler(ChannelHandlerContext ctx, CloseWebSocketFrame frame) {
        ctx.close();
    }

    /**
     * 创建连接之后，客户端发送的消息都会在这里处理
     * @param ctx

     */
    public static void textWebSocketFrameHandler(ChannelHandlerContext ctx, String code, String title, String message) {
        try {
            // 1. 参数校验
            if (ctx == null || !ctx.channel().isActive()) {
                log.error("WebSocket会话无效：上下文为空或通道未激活");
                return;
            }
            if (code == null || title == null || message == null) {
                log.error("参数为空: code={}, title={}, message={}", code, title, message);
                return;
            }

            // 2. 使用 JSON 库构造消息（避免手动拼接导致的格式错误）
            String json = String.format(
                    "{\"code\":%s, \"title\":\"%s\", \"message\":\"%s\"}",
                    code,
                    title.replace("\"", "\\\""),  // 转义特殊字符
                    message.replace("\"", "\\\"")
            );

            // 3. 异步发送并监听结果
            ctx.writeAndFlush(new TextWebSocketFrame(json))
                    .addListener(future -> {
                        if (!future.isSuccess()) {
                            log.error("消息发送失败: {}", future.cause().getMessage());
                        }
                    });
        } catch (Exception e) {
            log.error("WebSocket消息处理异常", e);
        }
    }
    /**
     * 创建连接之后，客户端发送的消息都会在这里处理
     * @param ctx

     */
    public static void ObjectWebSocketFrameHandler(ChannelHandlerContext ctx, Object object) {
        // 客户端发送过来的内容不进行业务处理，原样返回
        if(!CTX){
            return;
        }
        ctx.channel().writeAndFlush(object);
    }


    /**
     * 处理客户端心跳包
     * @param ctx
     * @param frame
     */
    private void pingWebSocketFrameHandler(ChannelHandlerContext ctx, PingWebSocketFrame frame) {
        ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
    }
}
